{
  Copyright 2012 Sergey Ostanin

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
}

unit TestScore;

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls, ComCtrls, TestSession, TestCore, VisualUtils, Math, MiscUtils,
  QuestionScore, SectionScore, TestUiUtils, DetailedAbout;

type
  TTestScoreFrame = class(TFrame)
    btnClose: TButton;
    lblAbout: TLabel;
    lblWeightRight: TLabel;
    lblWeightRightTitle: TLabel;
    lblQuestionCount: TLabel;
    lblQuestionCountTitle: TLabel;
    lblMark: TLabel;
    lblMarkTitle: TLabel;
    lblPartRight: TLabel;
    lblPartRightTitle: TLabel;
    pnlTotal: TPanel;
    pbxChart: TPaintBox;
    pgcMain: TPageControl;
    pnlBottom: TPanel;
    tsTotal: TTabSheet;
    procedure btnCloseClick(Sender: TObject);
    procedure lblAboutClick(Sender: TObject);
    procedure pbxChartPaint(Sender: TObject);
    procedure pnlTotalResize(Sender: TObject);
    procedure QuestionPageShow(Sender: TObject);
  private
    FSessionResult: TSessionResult;
    FQuestionScore: TQuestionScoreFrame;
    FSectionScore: TSectionScoreFrame;
    FQuestionPageShown: Boolean;
    procedure CloseHostForm;
    procedure Prepare(var SessionResult: TSessionResult;
      Questions: TQuestionList);
    procedure UpdateMarkLabelWidth;
    procedure SectionScoreActivateSection(Sender: TObject);
    procedure QuestionScoreSelectSection(Sender: TObject);
    { private declarations }
  public
    class procedure Embed(var SessionResult: TSessionResult;
      Questions: TQuestionList; Host: TWinControl);
    destructor Destroy; override;
    { public declarations }
  end;

implementation

{$R *.lfm}
{$R *.rc}

resourcestring
  SWeightRight = '%s of %d';
  SQuestions = 'Questions';
  SSections = 'Sections';

{ TTestScoreFrame }

procedure TTestScoreFrame.btnCloseClick(Sender: TObject);
begin
  CloseHostForm;
end;

procedure TTestScoreFrame.lblAboutClick(Sender: TObject);
begin
  TDetailedAboutForm.OpenModal('TestScore/NOTICE-PLAYER');
end;

procedure TTestScoreFrame.pbxChartPaint(Sender: TObject);
var
  a: Double;
  AllRight, AllWrong: Boolean;
  x1, y1, x2, y2, xc, yc: Integer;
  ColorRight, ColorWrong: TColor;
begin
  if FSessionResult.Policy.PercentCorrect then
  begin
    ColorRight := TDiagramColorScheme.GetColorForPartRight(1);
    ColorWrong := $c0c0c0;

    AllRight := FSessionResult.PartRight >= 0.997;
    AllWrong := FSessionResult.PartRight <= 0.004;

    pbxChart.Canvas.Pen.Color := clBlack;

    if AllRight or AllWrong then
    begin
      if AllRight then
        pbxChart.Canvas.Brush.Color := ColorRight
      else
        pbxChart.Canvas.Brush.Color := ColorWrong;
      pbxChart.Canvas.Ellipse(pbxChart.ClientRect);
    end
    else
    begin
      xc := pbxChart.ClientWidth div 2;
      yc := pbxChart.ClientHeight div 2;
      a := 2*Pi*FSessionResult.PartRight - Pi/2;
      x1 := Round((1 + Cos(a))*xc) - 1;
      y1 := Round((1 + Sin(a))*yc) - 1;
      x2 := xc - 1;
      y2 := 0;

      pbxChart.Canvas.Brush.Color := ColorRight;
      pbxChart.Canvas.Pie(0, 0, pbxChart.ClientWidth, pbxChart.ClientHeight, x1, y1, x2, y2);

      pbxChart.Canvas.Brush.Color := ColorWrong;
      pbxChart.Canvas.Pie(0, 0, pbxChart.ClientWidth, pbxChart.ClientHeight, x2, y2, x1, y1);
    end;
  end;
end;

procedure TTestScoreFrame.pnlTotalResize(Sender: TObject);
begin
  UpdateMarkLabelWidth;
end;

procedure TTestScoreFrame.QuestionPageShow(Sender: TObject);
begin
  if not FQuestionPageShown then
  begin
    if FQuestionScore <> nil then
      FQuestionScore.SelectQuestion(0);
    FQuestionPageShown := TRUE;
  end;
end;

procedure TTestScoreFrame.CloseHostForm;
var
  Form: TCustomForm;
begin
  Form := GetParentForm(Self);
  if Form <> nil then
    Form.Close;
end;

procedure TTestScoreFrame.Prepare(var SessionResult: TSessionResult;
  Questions: TQuestionList);
var
  h: Integer;
  QuestionPage, SectionPage: TTabSheet;
begin
  FSessionResult := SessionResult;
  SessionResult := nil;

  pbxChart.Width := ScalePixels(pbxChart.Width);
  pbxChart.Height := ScalePixels(pbxChart.Height);

  pnlTotal.Font.Size := 22;
  SetFontSize([lblQuestionCountTitle, lblQuestionCount,
    lblWeightRightTitle, lblWeightRight], 14);
  SetFontColor([lblPartRightTitle, lblMarkTitle,
    lblQuestionCountTitle, lblWeightRightTitle], clGrayText);

  h := pnlTotal.Canvas.TextHeight('|');
  pnlTotal.ChildSizing.HorizontalSpacing := h div 4;
  pnlTotal.ChildSizing.VerticalSpacing := h div 4;

  if FSessionResult.Policy.PercentCorrect then
    lblPartRight.Caption := Format('%d%%', [Round(FSessionResult.PartRight*100)])
  else
  begin
    lblPartRightTitle.Visible := FALSE;
    lblPartRight.Visible := FALSE;
    pbxChart.Visible := FALSE;
  end;

  if FSessionResult.Policy.Mark and (FSessionResult.Mark <> '') then
    lblMark.Caption := FSessionResult.Mark
  else
  begin
    lblMarkTitle.Visible := FALSE;
    lblMark.Visible := FALSE;
  end;

  lblQuestionCount.Caption := IntToStr(FSessionResult.QuestionCount);
  if FSessionResult.Policy.PercentCorrect or FSessionResult.Policy.Mark then
    lblQuestionCountTitle.BorderSpacing.Top := h;

  if FSessionResult.Policy.Points then
    lblWeightRight.Caption := Format(SWeightRight,
      [ConvertFloatToString(FSessionResult.WeightRight, 2, GetUiDecimalSeparator),
      FSessionResult.WeightTotal])
  else
  begin
    lblWeightRightTitle.Visible := FALSE;
    lblWeightRight.Visible := FALSE;
  end;

  UpdateMarkLabelWidth;

  if FSessionResult.Policy.QuestionResultsAvailable then
  begin
    QuestionPage := pgcMain.AddTabSheet;
    QuestionPage.Caption := SQuestions;
    QuestionPage.OnShow := QuestionPageShow;
    FQuestionScore := TQuestionScoreFrame.Create(nil);
    FQuestionScore.Parent := QuestionPage;
    FQuestionScore.SetUp(FSessionResult, Questions);
    FQuestionScore.OnSelectSection := QuestionScoreSelectSection;
  end;

  if FSessionResult.Policy.SectionResultsAvailable
    and (FSessionResult.SectionResultCount > 1) then
  begin
    SectionPage := pgcMain.AddTabSheet;
    SectionPage.Caption := SSections;
    FSectionScore := TSectionScoreFrame.Create(nil);
    FSectionScore.Parent := SectionPage;
    FSectionScore.SetUp(FSessionResult);
    FSectionScore.OnActivateSection := SectionScoreActivateSection;
  end;
end;

procedure TTestScoreFrame.UpdateMarkLabelWidth;
begin
  SetFixedWidthConstraint(lblMark, Max(pnlTotal.ClientWidth - lblMark.Left, 1));
end;

procedure TTestScoreFrame.SectionScoreActivateSection(Sender: TObject);
begin
  if FSessionResult.Policy.SectionQuestionList
    and (FQuestionScore <> nil) then
  begin
    pgcMain.ActivePage := FQuestionScore.Parent as TTabSheet;
    FQuestionScore.SelectedSectionIndex := FSectionScore.SelectedSectionIndex;
  end;
end;

procedure TTestScoreFrame.QuestionScoreSelectSection(Sender: TObject);
begin
  if FSectionScore <> nil then
    FSectionScore.SelectedSectionIndex := FQuestionScore.SelectedSectionIndex;
end;

class procedure TTestScoreFrame.Embed(var SessionResult: TSessionResult;
  Questions: TQuestionList; Host: TWinControl);
var
  f: TTestScoreFrame;
begin
  f := TTestScoreFrame.Create(Host);
  try
    f.Parent := Host;
    f.Prepare(SessionResult, Questions);
  except
    f.Free;
    raise;
  end;
end;

destructor TTestScoreFrame.Destroy;
begin
  FreeAndNil(FQuestionScore);
  FreeAndNil(FSectionScore);
  FreeAndNil(FSessionResult);
  inherited;
end;

end.

